package org.linlinjava.litemall.core.payment.clover.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import okhttp3.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.linlinjava.litemall.core.payment.DefaultCurType;
import org.linlinjava.litemall.core.payment.PaymentResponseCode;
import org.linlinjava.litemall.core.payment.clover.rq.ApiCardRQ;
import org.linlinjava.litemall.core.payment.clover.rq.ApiChargeRQ;
import org.linlinjava.litemall.core.payment.clover.rq.ApiRefundRQ;
import org.linlinjava.litemall.core.payment.clover.rq.ApiTokenRQ;
import org.linlinjava.litemall.core.payment.clover.rs.*;
import org.linlinjava.litemall.core.payment.clover.service.CloverService;
import org.linlinjava.litemall.core.payment.clover.service.CloverTokenManager;
import org.linlinjava.litemall.core.payment.paypal.service.impl.CardPaypalServiceImpl;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.db.beans.Constants;
import org.linlinjava.litemall.db.domain.LitemallGiftCardOrder;
import org.linlinjava.litemall.db.domain.LumiereIdcard;
import org.linlinjava.litemall.db.service.LitemallGiftCardOrderService;
import org.linlinjava.litemall.db.service.LumiereIdCardService;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;

import static org.linlinjava.litemall.core.payment.PaymentResponseCode.CLOVER_TOKEN_NOT_EXIST;

public class CardCloverServiceImpl implements CloverService {

    private final Log logger = LogFactory.getLog(CardCloverServiceImpl.class);

    @Autowired
     private LitemallGiftCardOrderService cardOrderService;

    @Autowired
    private LumiereIdCardService idCardService;

    @Override
    public Object getPayment(Integer userId, Integer orderId, String successUrl, String cancelUrl) {
        return null;
    }

    @Override
    public Object executePayment(String cardNumber,Integer userId,Integer orderId) throws IOException{
//        LumiereIdcard idcard =  idCardService.findById(cardId);
        LitemallGiftCardOrder cardOrder = cardOrderService.findById(orderId);
        ApiChargeRQ apiChargeRQ = new ApiChargeRQ();
        apiChargeRQ.setAmount(cardOrder.getAmount());
        apiChargeRQ.setCurrency("CAD");
//        ApiTokenRS apiTokenRS = getTokenRS(cardId);
//        apiChargeRQ.setSource(apiTokenRS.getId());

        String cloverToken = CloverTokenManager.getCloverToken(cardNumber,userId);

        if(cloverToken == null){
            return ResponseUtil.fail(CLOVER_TOKEN_NOT_EXIST, "支付token不存在");
        }

        apiChargeRQ.setSource(cloverToken);

        OkHttpClient client = new OkHttpClient();

        MediaType mediaType = MediaType.parse("application/json");
        RequestBody body = RequestBody.create(mediaType, JSON.toJSONString(apiChargeRQ));
        Request request = new Request.Builder()
                .url("https://scl-sandbox.dev.clover.com/v1/charges")
                .post(body)
                .addHeader("Accept", "application/json")
                .addHeader("Content-Type", "application/json")
                .addHeader("Authorization", "Bearer db53131e-3a30-b771-343c-7d865da81c97")
                .build();

        Response response = client.newCall(request).execute();
        JSONObject vo =  (JSONObject)JSON.parse(response.body().string());
        ApiChargeRS apiChargeRS = new ApiChargeRS();

        apiChargeRS.setMessage(vo.getString("message"));

        if(vo.getString("status").equals("succeeded")){
            if (cardOrder == null) {
                return ResponseUtil.fail(PaymentResponseCode.ORDER_UNKNOWN, "订单不存在");
            }

            // 检查这个订单是否已经处理过
            if (cardOrder.getPayStatus() == Constants.PAY_STATUS_DONE || cardOrder.getPayId() != null) {
                return ResponseUtil.fail(PaymentResponseCode.PAYMENT_FAIL, "订单已经处理成功!");
            }

            // 检查支付订单金额
            BigDecimal totalFee = vo.getBigDecimal("amount");
            if (!totalFee.toString().equals(cardOrder.getAmount().toString())) {
                return ResponseUtil.fail(PaymentResponseCode.PAYMENT_FAIL, " : 支付金额不符合 totalFee=" + totalFee);
            }

            LitemallGiftCardOrder update = new LitemallGiftCardOrder();
            update.setPayType(Constants.PAY_TYPE_CLOVER);
            update.setCurrency(DefaultCurType.CAD.getType());
            cardOrder.setTransationId(vo.getString("id"));
            update.setPayTime(LocalDateTime.now());
            update.setPayStatus(Constants.PAY_STATUS_DONE);

            logger.debug("更新订单信息");
            if (cardOrderService.payDone(cardOrder, update) == 0) {
                return ResponseUtil.updatedDateExpired();
            }

            apiChargeRS.setStatus(vo.getString("status"));

            return apiChargeRS;
        }else{
            logger.info("gift card executePayment error : "+ vo);
            return ResponseUtil.fail(PaymentResponseCode.PAYMENT_FAIL, "支付失败");
        }
    }

    @Override
    public boolean refund(Integer orderId) throws IOException {
        LitemallGiftCardOrder order = cardOrderService.findById(orderId);
        ApiRefundRQ apiRefundRQ = new ApiRefundRQ();
       if(order.getTransationId() == null){
           return false;
       }else{
           apiRefundRQ.setCharge(order.getTransationId());
           apiRefundRQ.setAmount(order.getAmount());
           apiRefundRQ.setReason("fraudulent");

           OkHttpClient client = new OkHttpClient();

           MediaType mediaType = MediaType.parse("application/json");
           RequestBody body = RequestBody.create(mediaType, JSON.toJSONString(apiRefundRQ));
           Request request = new Request.Builder()
                   .url("https://scl-sandbox.dev.clover.com/v1/refunds")
                   .post(body)
                   .addHeader("Accept", "application/json")
                   .addHeader("Content-Type", "application/json")
                   .addHeader("Authorization", "Bearer db53131e-3a30-b771-343c-7d865da81c97")
                   .build();

           Response response = client.newCall(request).execute();
           JSONObject vo =  (JSONObject)JSON.parse(response.body().string());
           if(vo.getString("status").equals("succeeded")){
               return true;
           }else{
               return false;
           }
       }
//        return false;
    }

    @Override
    public List<ApiCustomerRS> getCustomerCards(String customerId) throws IOException {
        return null;
    }

    public ApiKeyRS getKeyRS() throws IOException {
        OkHttpClient client = new OkHttpClient();

        Request request = new Request.Builder()
                .url("https://apisandbox.dev.clover.com/pakms/apikey")
                .get()
                .addHeader("Accept", "application/json")
                .addHeader("Authorization", "Bearer db53131e-3a30-b771-343c-7d865da81c97")
                .build();

        Response response = client.newCall(request).execute();

        JSONObject vo =  (JSONObject) JSON.parse(response.body().string());

        ApiKeyRS keyVo = new ApiKeyRS();
        keyVo.setActive( (Boolean )vo.get("active"));
        keyVo.setApiAccessKey(vo.getString("apiAccessKey"));
        keyVo.setMerchantUuid(vo.getString("merchantUuid"));
        keyVo.setDeveloperAppUuid(vo.getString("developerAppUuid"));
        keyVo.setCreatedTime(vo.getString("createdTime"));
        keyVo.setModifiedTime(vo.getString("modifiedTime"));
        return keyVo;
    }

    public ApiTokenRS getTokenRS(Integer cardId ) throws IOException {
        LumiereIdcard idcard = idCardService.findById(cardId);
        OkHttpClient client = new OkHttpClient();
        ApiKeyRS keyRS = getKeyRS();
        ApiCardRQ cardRQ = new ApiCardRQ();
        cardRQ.setNumber(idcard.getCardNo());
        cardRQ.setExp_month(idcard.getExpiredMonth().toString());
        cardRQ.setExp_year(idcard.getExpiredYear().toString());
        cardRQ.setCvv(idcard.getCvv());
        cardRQ.setBrand(idcard.getType());
        cardRQ.setLast4(cardRQ.getNumber().substring(cardRQ.getNumber().length() - 4, cardRQ.getNumber().length()));
        cardRQ.setFirst6(cardRQ.getNumber().substring(0,6));
        cardRQ.setCountry("CAD");

        ApiTokenRQ rq = new ApiTokenRQ();
        rq.setCard(cardRQ);

        MediaType mediaType = MediaType.parse("application/json");
        RequestBody body = RequestBody.create(mediaType, JSON.toJSONString(rq));
        Request request = new Request.Builder()
                .url("https://token-sandbox.dev.clover.com/v1/tokens")
                .post(body)
                .addHeader("Accept", "application/json")
                .addHeader("apikey", keyRS.getApiAccessKey())
                .addHeader("Content-Type", "application/json")
                .build();

        Response response = client.newCall(request).execute();
        JSONObject vo =  (JSONObject)JSON.parse(response.body().string());
        ApiTokenRS tokenVo = new ApiTokenRS();
        tokenVo.setId(vo.getString("id"));
        return tokenVo;
    }
}
